package com.moro.lisp.tools;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.moro.lisp.JLispData;
import com.moro.lisp.JLispFunctionName;
import com.moro.lisp.JLispMacroName;
import com.moro.lisp.JLispType;
import com.moro.lisp.os.Terminal;
import com.moro.lisp.typedefine.Atom;
import com.moro.lisp.typedefine.Cons;
import com.moro.lisp.typedefine.Error;
import com.moro.lisp.typedefine.Function;
import com.moro.lisp.typedefine.Macro;
/**
 * 宏池，终端所有的宏由此宏池管理
 * @author HJ
 *
 */
public class MacroPool {
	private List<Macro> pool;
	
	
	/*
	 * 默认构造方法
	 */
	public MacroPool(SymbolPool symbolPool) {
		this.pool = new ArrayList<Macro>();
		macroInit(symbolPool);
	}
	public void macroInit(SymbolPool symbolPool) {
		//初始化基本宏
		this.pool.add(new Macro(JLispMacroName.QUOTE, symbolPool.getSymbolByString("quote"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.REVERSEQUOTE, symbolPool.getSymbolByString("reversequote"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.COMMA, symbolPool.getSymbolByString("comma"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.SETQ, symbolPool.getSymbolByString("setq"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.SETF, symbolPool.getSymbolByString("setf"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.DO, symbolPool.getSymbolByString("do"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.LET, symbolPool.getSymbolByString("let"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.DEFUN, symbolPool.getSymbolByString("defun"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.DEFMACRO, symbolPool.getSymbolByString("defmacro"),
				symbolPool.getSymbolByString("nil"), null, null));
		this.pool.add(new Macro(JLispMacroName.COMMAT, symbolPool.getSymbolByString("commat"),
				symbolPool.getSymbolByString("nil"), null, null));
	}
	
	
	
	/*
	 * 根据函数名和符号查找函数
	 */
	/*public Function getFunction(JLispFunctionName functionName, Atom atom) {
		return null;
	}*/
	
	
	
	/*
	 * 根据函数名（枚举类型）符号定义函数(注意不能定义基本函数，因为基本函数在构建函数池时已被定义，但是可以用相同的符号比如if定义其它函数)
	 */
	public Macro getMacroByMacroName(JLispMacroName macroName,
			Atom atom,Cons args,List<JLispData> macroBodys, List<Atom> closure) {
		if(JLispMacroName.CUSTOMIZE != macroName) {
			return null;
		}else {
			Macro macro = new Macro(macroName, atom, args, macroBodys, closure);
			addMacro(macro);
			return macro;
		}
		
	}
	public Macro getMacroByMacroName(JLispMacroName macroName,
			Atom atom,Atom nil,List<JLispData> macroBodys, List<Atom> closure) {
		if(JLispMacroName.CUSTOMIZE != macroName) {
			return null;
		}else {
			Macro macro = new Macro(macroName, atom, nil, macroBodys, closure);
			addMacro(macro);
			return macro;
		}
		
	}
	private void addMacro(Macro macro) {
		if(JLispMacroName.CUSTOMIZE != macro.macroName) {//如果不是自定义函数，则不添加
			return;
		}else {
			this.pool.add(macro);
		}
	}
	private void removeMacro(int i, SymbolPool symbolPool) {
		if(null == this.pool.get(i).closure) {
			this.pool.remove(i);
			return;
		}
		for(Atom a:this.pool.get(i).closure) {
			symbolPool.findByString(a.name).symbolValues.rBind(new JLispData(this.pool.get(i), JLispType.MACRO));
		}
		this.pool.remove(i);
	}
	public void flush(SymbolPool symbolPool) {
		for(int i = 10;i < this.pool.size();i++) {
			if(!this.pool.get(i).isAlive()) {
				this.removeMacro(i--, symbolPool);;
			}
		}
	}
	public int getMacroPoolSize() {
		return this.pool.size();
	}
}
